package org.chispa.api.processor;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.chispa.api.domain.DomainRetriever;
import org.chispa.api.domain.DomainRetrieverFactory;
import org.chispa.api.util.ExpressionLanguage;

class SimpleSparqlProc<T> implements QueryProcessor<String, T> {
	
	private String query;
	
	private Set<String> secureParams=new HashSet<String>();
	
	SimpleSparqlProc(String query){
		this.query=query;
	}
	
	private static class PlaceHolderHelper{
		
		private String query;
		private List<String> params;
		private String placeholder;
		
		public PlaceHolderHelper(String query,String placeholder,List<String> params)
		{
			this.query=query;
			this.params=params;
			this.placeholder=placeholder;
		}
		
		public List<String> getParams() {
			return params;
		}
		
		public String getQuery() {
			return query;
		}

		public String getPlaceholder() {
			return placeholder;
		}
	}

	@Override
	public String preprocess() {
		return preprocess(query);
	}
	
	@Override
	public String preprocess(String query) {

		PlaceHolderHelper helper=replaceWithPlaceHolder(query);
		query=helper.getQuery();
		query=query.replace("\t", " ");
		query=query.replace(System.getProperty("line.separator"), " ");
		query=query.replaceAll("\\s*\\|\\|\\s*", " || ");
		query=query.replaceAll("\\s*\\&\\&\\s*", " && ");
		query=query.replaceAll("\\s*\\(", " ( ").replaceAll("\\s*\\)", " ) ");
		query=query.replaceAll("\\s*\\,\\s*", " , ");
		
		Pattern pattern=Pattern.compile(ExpressionLanguage.SECURE_REGEX,Pattern.CASE_INSENSITIVE);
		Matcher match=pattern.matcher(query);
		while(match.find())
		{
			String token=match.group();
			String param=token.replaceAll("(?i)"+ExpressionLanguage.SECURE_PREFIX, "").trim();
			secureParams.add(param);
			query=query.replace(token, param);
		}
		collectNamespaces();
		query=replaceWithParameters(query,helper.getPlaceholder(), helper.getParams());
		return query;
	}
	
	private String replaceWithParameters(String query,String placeholder,List<String> literals)
	{
		for(int i=0;i<literals.size();i++)
		{
			query=query.replace(placeholder+i, literals.get(i));
		}
		return query;
	}
	
	public boolean isSecure(String param)
	{
		return secureParams.contains(param);
	}
	
	private PlaceHolderHelper replaceWithPlaceHolder(String query)
	{
		String placeholder=generatePlaceholder(query);
		String wicked_evil_regex=ExpressionLanguage.LITERAL_REGEX;
		ArrayList<String> literals=new ArrayList<String>();
		Pattern pattern=Pattern.compile(wicked_evil_regex);
		Matcher match=pattern.matcher(query);
		int i=0;
		while(match.find())
		{
			String token=match.group();
			literals.add(token);
			query=query.replace(token, placeholder+i);
			i++;
		}
		return new PlaceHolderHelper(query,placeholder,literals);
	}
	
	private void collectNamespaces()
	{
		DomainRetriever domR=DomainRetrieverFactory.getInstance();
		Pattern pattern=Pattern.compile(ExpressionLanguage.PREFIX_REGEX,Pattern.CASE_INSENSITIVE);
		Matcher match=pattern.matcher(query);
		while(match.find())
		{
			String token=match.group().replaceAll("\\s+", " ");
			String[]members=token.split(" ");
			domR.registerNamespace(members[2],members[1]);
		}
	}
	
	private String generatePlaceholder(String query)
	{
		String placeholder="";
		int i=0;
		while(i<query.length()+1)
		{
			i++;
			placeholder+="X";
		}
		return placeholder;
	}


}
